#include "Triangle.h"

Triangle::Triangle()
{
	pointA = D3DXVECTOR3(1, 0, 0);
	pointB = D3DXVECTOR3(0, 1, 0);
	pointC = D3DXVECTOR3(0, 0, 1);
	
	colour = Colour(0.5, 0.5, 0.5, 0.0f);

	
	D3DXVECTOR3 CToA(pointC - pointA);
	D3DXVECTOR3 BToA(pointB - pointA);

	D3DXVec3Cross(&m_normal, &CToA, &BToA);
	D3DXVec3Normalize(&m_normal, &m_normal);
}

Triangle::Triangle(const D3DXVECTOR3& A, const D3DXVECTOR3 B, const D3DXVECTOR3 C, const Colour& col)
{
	colour = col;
	pointA = A;
	pointB = B;
	pointC = C;

	D3DXVECTOR3 CToA(pointC - pointA);
	D3DXVECTOR3 BToA(pointB - pointA);

	D3DXVec3Cross(&m_normal, &CToA, &BToA);
	D3DXVec3Normalize(&m_normal, &m_normal);
}

float Triangle::FindIntersection(const Ray& ray)
{
	D3DXVECTOR3 normal = m_normal;

	float distance = Distance();
	float a = D3DXVec3Dot(&ray.GetDirection(), &normal);

	if (a == 0)
	{
		// ray == parralel to triangle
		return -1;
	}
	else
	{
		float b = D3DXVec3Dot(&normal, &D3DXVECTOR3(ray.GetOrigin() + (normal * distance) * -1.0f));
		float distanceToPlane = -1.0f * b / a;

		float Wx = D3DXVECTOR3(ray.GetDirection() * distanceToPlane).x + ray.GetOrigin().x;
		float Wy = D3DXVECTOR3(ray.GetDirection() * distanceToPlane).y + ray.GetOrigin().y;
		float Wz = D3DXVECTOR3(ray.GetDirection() * distanceToPlane).z + ray.GetOrigin().z;

		D3DXVECTOR3 W(Wx, Wy, Wz);

		D3DXVECTOR3 CToA(pointC - pointA);
		D3DXVECTOR3 WToA(W - pointA);
		D3DXVECTOR3 crossProd1;
		D3DXVec3Cross(&crossProd1, &CToA, &WToA);
		float test1 = D3DXVec3Dot(&crossProd1, &normal);

		D3DXVECTOR3 BtoC(pointB - pointC);
		D3DXVECTOR3 WtoC(W - pointC);
		D3DXVECTOR3 crossProd2;
		D3DXVec3Cross(&crossProd2, &BtoC, &WtoC);
		float test2 = D3DXVec3Dot(&crossProd2, &normal);
		
		D3DXVECTOR3 AtoB(pointA - pointB);
		D3DXVECTOR3 WtoB(W - pointB);
		D3DXVECTOR3 crossProd3;
		D3DXVec3Cross(&crossProd3, &AtoB, &WtoB);
		float test3 = D3DXVec3Dot(&crossProd3, &normal);

		if (test1 >= 0 && test2 >= 0 && test3 >= 0)
		{
			return distanceToPlane;
		}
		else
		{
			return -1;
		}
	}
}

D3DXVECTOR3 Triangle::GetNormal()
{
	return m_normal;
}

const D3DXVECTOR3& Triangle::GetNormalAt(const D3DXVECTOR3& coord)
{
	return m_normal;
}

float Triangle::Distance()
{
	return D3DXVec3Dot(&m_normal, &pointA);
}
